#ifndef OGREREFAPPREGION_H
#define OGREREFAPPREGION_H
//------------------------------------------------------------------------
//
//  Name:   State.h
//
//  Desc:   abstract base class to define an interface for a state
//
//  Author: Mat Buckland (fup@ai-junkie.com)
//
//------------------------------------------------------------------------
#include <OgreVector2.h>
#include "OgreRefAppConstants.h"
#include "OgreRefAppUtils.h"

namespace OgreRefApp
{


    class Region
    {
    public:

        enum region_modifier{halfsize, normal};

    protected:

        Real        m_dTop;
        Real        m_dLeft;
        Real        m_dRight;
        Real        m_dBottom;

        Ogre::Vector2     m_vCenter;

        int          m_iID;

    public:

        Region():m_dTop(0.0),m_dBottom(0.0),m_dLeft(0.0),m_dRight(0.0)
        {}


        Region( Ogre::Vector2 v, int id ):m_dTop(v.y * TileHeight + TileHeight),
                m_dRight(v.x * TileWidth + TileWidth ),
                m_dLeft(v.x * TileWidth),
                m_dBottom(v.y * TileHeight),
                m_iID(id)
        {
            //calculate center of region
            m_vCenter = Ogre::Vector2( (m_dLeft+m_dRight)*0.5, (m_dTop+m_dBottom)*0.5 );

        }

        Region(Real left,
         Real top,
         Real right,
         Real bottom,
         int id = -1):m_dTop(top),
                        m_dRight(right),
                        m_dLeft(left),
                        m_dBottom(bottom),
                        m_iID(id)
        {
        //calculate center of region
        m_vCenter = Ogre::Vector2( (m_dLeft+m_dRight)*0.5, (m_dTop+m_dBottom)*0.5 );

        }

        virtual ~Region(){}


        //returns true if the given position lays inside the region. The
        //region modifier can be used to contract the region bounderies
        inline bool     Inside(Ogre::Vector2 pos, region_modifier r)const;

        //returns a vector representing a random location
        //within the region
        inline Ogre::Vector2 GetRandomPosition()const;

        //-------------------------------
        Real     Top()const
        {
            return m_dTop;
        }
        Real     Bottom()const
        {
            return m_dBottom;
        }
        Real     Left()const
        {
            return m_dLeft;
        }
        Real     Right()const
        {
            return m_dRight;
        }
        Real     Width()const
        {
            return fabs(m_dRight - m_dLeft);
        }
        Real     Height()const
        {
            return fabs(m_dTop - m_dBottom);
        }
        Real     Length()const
        {
            return std::max(Width(), Height());
        }
        Real     Breadth()const
        {
            return std::min(Width(), Height());
        }

        Ogre::Vector2  Center()const
        {
            return m_vCenter;
        }
        int       ID()const
        {
            return m_iID;
        }

    };



    inline Ogre::Vector2 Region::GetRandomPosition()const
    {
        return Ogre::Vector2(OgreRefApp::RandInRange(m_dLeft, m_dRight),
                             RandInRange(m_dTop, m_dBottom));
    }

    inline bool Region::Inside(Ogre::Vector2 pos, region_modifier r=normal)const
    {
        if (r == normal)
        {
            return ((pos.x > m_dLeft) && (pos.x < m_dRight) &&
                    (pos.y < m_dTop) && (pos.y > m_dBottom));
        }
        else
        {
            const Real marginX = Width() * 0.25;
            const Real marginY = Height() * 0.25;

            return ((pos.x > (m_dLeft+marginX)) && (pos.x < (m_dRight-marginX)) &&
                    (pos.y < (m_dTop+marginY)) && (pos.y > (m_dBottom-marginY)));
        }

    }



}
#endif
